import type { WebDesignerAgencyInfo, WebDesignerComponentData, XuanXiaoHomeIndex } from '@/api/designer/model'
import type { Exposed as CourseCategoryModalExposed } from '@/components/CourseCategoryModal/type'
import type { Exposed as IconSelectModalExposed } from '@/components/IconSelectModal/type'
import type { Exposed as JumpLinkModalExposed } from '@/components/JumpLinkModal/type'
import type { Exposed as VideoPreviewModalExposed } from '@/components/VideoPreviewModal/type'
import type { ComponentMeta } from '@/definitions/type'
import { getApiDesignerPlatformAgency, getApiDesignerPlatformAgencyDataAgencyId, postApiDesignerPlatformAgency } from '@/api/designer/designer'
import { componentDefinitionMap, entryQuery } from '@/definitions/component-definition'
import { defaultDesignerThemeColor } from '@/utils/constants'
import { getDesignerThemeColorLight, isColorMatches, toUnifiedFormatColor, withResolvers } from '@/utils/helper'
import { defineStore } from 'pinia'
import { markRaw, nextTick, ref, watch } from 'vue'
import { useDesignStore } from './design'

const { promise, resolve } = withResolvers()

export const useInstStore = defineStore('inst', () => {
  const detail = ref<Nullable<WebDesignerAgencyInfo>>()
  const jumpData = ref<Nullable<XuanXiaoHomeIndex>>()
  const jumpDataLoading = ref<boolean>(false)
  const compRefs = markRaw({
    JumpLinkModalRef: ref<Nullable<JumpLinkModalExposed>>(null),
    IconSelectModalRef: ref<Nullable<IconSelectModalExposed>>(null),
    VideoPreviewModalRef: ref<Nullable<VideoPreviewModalExposed>>(null),
    CourseCategoryModalRef: ref<Nullable<CourseCategoryModalExposed>>(null),
  })
  watch(() => detail.value?.themeColor, () => {
    setDesignThemeColorVariables()
  })
  async function loadInstDetail() {
    const { platform, agencyId, pageId } = entryQuery
    const designStore = useDesignStore()
    designStore.toggleGlobalSpin(true)
    try {
      const result = await getApiDesignerPlatformAgency(platform!, {
        agencyId: Number(agencyId),
        pageId: Number(pageId),
      })
      const { list, ...info } = result
      if (!info.themeColor) {
        info.themeColor = defaultDesignerThemeColor
      }
      info.themeColor = toUnifiedFormatColor(info.themeColor)
      detail.value = info
      // sync configured components
      if (list && list.length > 0) {
        const renders: ComponentMeta[] = []
        list.forEach((l) => {
          renders.push({
            id: l.id,
            config: l.data ? JSON.parse(l.data) : {},
            definition: componentDefinitionMap.get(l.code as any)!.definition,
          })
        })
        designStore.renders.push(...renders)
      }
    }
    finally {
      designStore.toggleGlobalSpin(false)
    }
  }

  async function saveInstDesignData() {
    const designStore = useDesignStore()
    designStore.toggleGlobalSpin(true, '处理中...')
    try {
      const { platform } = entryQuery
      const list = await getRenderContent()
      designStore.toggleGlobalSpin('保存中...')

      return await postApiDesignerPlatformAgency(platform as string, {
        ...detail.value!,
        list,
        // 全局样式保存
        // 获取全局样式变量，以 --design 开头的变量
        css: document.documentElement.style.cssText,
      })
    }
    finally {
      designStore.toggleGlobalSpin(false)
    }
    async function getRenderContent(): Promise<WebDesignerComponentData[]> {
      function getTemplateHtml(id: string) {
        let html = ''
        const hostEl = document.querySelector(`#${id}`)
        if (hostEl) {
          html += hostEl.outerHTML
        }
        return html
      }
      return new Promise((resolve) => {
        const list = designStore.renders.map((r) => {
          return {
            id: r.id!,
            sort: r.definition.sort,
            code: r.definition.code,
            data: JSON.stringify(r.config),
            // html,
            // htmlPc
          } as WebDesignerComponentData
        })
        const ids = designStore.renders.map(r => r.id)
        if (ids.length > 0) {
          const currentPlatform = designStore.config.platform
          let tip = currentPlatform === 'mobile' ? '正在获取移动端HTML内容...' : '正在获取PC端HTML内容...'
          let field: 'html' | 'htmlPc' = currentPlatform === 'mobile' ? 'html' : 'htmlPc'
          designStore.toggleGlobalSpin(tip)
          list.forEach((l) => {
            l[field] = getTemplateHtml(l.id!)
          })
          // 获取另一个平台的html模板内容
          const anotherPlatform = currentPlatform === 'mobile' ? 'pc' : 'mobile'
          tip = anotherPlatform === 'mobile' ? '正在获取移动端HTML内容...' : '正在获取PC端HTML内容...'
          field = anotherPlatform === 'mobile' ? 'html' : 'htmlPc'
          designStore.config.platform = anotherPlatform
          designStore.toggleGlobalSpin(tip)
          nextTick(() => {
            list.forEach((l) => {
              l[field] = getTemplateHtml(l.id!)
            })
            // back to current platform
            designStore.config.platform = currentPlatform
            resolve(list)
          })
        }
        else {
          resolve([])
        }
      })
    }
  }
  function setDesignThemeColorVariables() {
    if (detail.value) {
      const FALLBACK_COLOR = 'transparent'
      const hostEl = document.documentElement
      const isValid = isColorMatches(detail.value.themeColor as string)
      hostEl.style.setProperty('--design-theme-color', isValid ? detail.value.themeColor! : FALLBACK_COLOR)
      hostEl.style.setProperty('--design-theme-color-light', isValid ? getDesignerThemeColorLight(detail.value.themeColor!) : FALLBACK_COLOR)
      hostEl.style.setProperty('--design-theme-color-lightest', isValid ? getDesignerThemeColorLight(detail.value.themeColor!, 0.1) : FALLBACK_COLOR)
    }
  }
  function getCurrentDesignerThemeColor() {
    const hostEl = document.documentElement
    return {
      themeColor: hostEl.style.getPropertyValue('--design-theme-color'),
      themeColorLight: hostEl.style.getPropertyValue('--design-theme-color-light'),
      themeColorLightest: hostEl.style.getPropertyValue('--design-theme-color-lightest'),
    }
  }
  async function loadJumpData() {
    if (jumpDataLoading.value)
      return promise
    async function _loadJumpData() {
      const { agencyId, platform } = entryQuery
      const designStore = useDesignStore()
      try {
        jumpDataLoading.value = true
        designStore.toggleGlobalSpin(true)
        jumpData.value = await getApiDesignerPlatformAgencyDataAgencyId(Number(agencyId), platform!)
      }
      finally {
        resolve()
        jumpDataLoading.value = false
        designStore.toggleGlobalSpin(false)
      }
    }
    _loadJumpData()
    return promise
  }
  return {
    detail,
    jumpData,
    jumpDataLoading,
    compRefs,
    loadInstDetail,
    saveInstDesignData,
    setDesignThemeColorVariables,
    getCurrentDesignerThemeColor,
    loadJumpData,
  }
})
